package com.chhuang.huaao.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSONObject;
import com.chhuang.huaao.controller.AdminController;
import com.chhuang.huaao.controller.ClientController;
import com.chhuang.huaao.thread.TokenFileThread;
import com.chhuang.system.consts.SysConstants;
import com.chhuang.utils.Assert;
import com.chhuang.utils.config.SysConfig;

/**
 * APP登录校验
 * @author CHHUANG
 *
 */
public class AppLoginFilter implements Filter {
	private static final Log log = LogFactory.getLog(AppLoginFilter.class);
	
	protected boolean autoLogin = false;
	protected long overdueDays = 30l;
	private static String skips[] = null;

	private static final String APP_KEY = "App-Key";
	private static final String APP_TOKEN = "App-Token";
	
	@Override
	public void init(FilterConfig config) throws ServletException {
		String value = config.getInitParameter("autoLogin");
		if (value != null && (value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true"))) {
			autoLogin = true;
		}
		String skip = config.getInitParameter("skip");
		if (skip != null) {
			skips = skip.split(";");
		}
		String overdue = config.getInitParameter("overdueDays");
		if(Assert.isValidString(overdue) && StringUtils.isNumeric(overdue)){
			overdueDays = Long.parseLong(overdue);
		}
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest hrequest = (HttpServletRequest)request;
		HttpServletResponse hresponse=(HttpServletResponse)response;
		
		if(autoLogin){
			chain.doFilter(request,response);
			return;
		}
		if (skips != null && this.needSkipUserLoginCheck(hrequest)){
			chain.doFilter(request,response);
			return;
		}
		
		String appKey = hrequest.getHeader(APP_KEY);
		String appToken = hrequest.getHeader(APP_TOKEN);
		if(Assert.isInvalidString(appKey) || Assert.isInvalidString(appToken)){//没有登录，无法使用
			log.info("APP没有登录，无法使用");
			hrequest.getRequestDispatcher("/client/api/relogin.app").forward(hrequest, hresponse);
		}else{
			String uri = hrequest.getRequestURI();
			long now = System.currentTimeMillis();
			if(uri.indexOf("/client/api")>-1){//校验是否是client app登录
				JSONObject token = ClientController.tokens.get(appKey);
				if(token!=null){
					long time = token.getLong(SysConstants.Token.TIME);
					String ttoken = token.getString(SysConstants.Token.TOKEN);
					if(now-time > overdueDays*86400000l || !appToken.equals(ttoken)){//登录过期或者token不相同，无法使用
						log.info("APP登录过期或者token不相同，无法使用");//也可能在其它手机上有人登录使用了
						ClientController.tokens.remove(appKey);
						//把token写入文件
						new Thread(new TokenFileThread(ClientController.tokens, SysConfig.getValue(SysConstants.Config.CLIENT_TOKEN_PATH))).start();
						hrequest.getRequestDispatcher("/client/api/relogin.app").forward(hrequest, hresponse);
					}else if(uri.indexOf("findCustomer.app")>-1){//如果在过期前又登录了，则修改token中的时间参数
						token.put(SysConstants.Token.TIME, now);
						ClientController.tokens.put(appKey, token);
						//把token写入文件
						new Thread(new TokenFileThread(ClientController.tokens, SysConfig.getValue(SysConstants.Config.CLIENT_TOKEN_PATH))).start();
						chain.doFilter(request,response);
					}else{
						chain.doFilter(request,response);
					}
				}else{//token不存在，无法使用
					log.info("token不存在，无法使用");
					hrequest.getRequestDispatcher("/client/api/relogin.app").forward(hrequest, hresponse);
				}
			}else if(uri.indexOf("/admin/api")>-1){//校验是否是admin app登录
				JSONObject token = AdminController.tokens.get(appKey);
				if(token!=null){
					long time = token.getLong(SysConstants.Token.TIME);
					String ttoken = token.getString(SysConstants.Token.TOKEN);
					if(now-time > overdueDays*86400000l || !appToken.equals(ttoken)){//登录过期或者token不相同，无法使用
						log.info("APP登录过期或者token不相同，无法使用。");//也可能在其它手机上有人登录使用了
						AdminController.tokens.remove(appKey);
						//把token写入文件
						new Thread(new TokenFileThread(AdminController.tokens, SysConfig.getValue(SysConstants.Config.ADMIN_TOKEN_PATH))).start();
						hrequest.getRequestDispatcher("/admin/api/relogin.app").forward(hrequest, hresponse);
					}else if(uri.indexOf("findUser.app")>-1){//如果在过期前又登录了，则修改token中的时间参数
						token.put(SysConstants.Token.TIME, now);
						AdminController.tokens.put(appKey, token);
						//把token写入文件
						new Thread(new TokenFileThread(AdminController.tokens, SysConfig.getValue(SysConstants.Config.ADMIN_TOKEN_PATH))).start();
						chain.doFilter(request,response);
					}else{
						chain.doFilter(request,response);
					}
				}else{//token不存在，无法使用
					log.info("token不存在，无法使用");
					hrequest.getRequestDispatcher("/admin/api/relogin.app").forward(hrequest, hresponse);
				}
			}else{
				chain.doFilter(request,response);
			}
		}
		
	}
	
	@Override
	public void destroy() {
		autoLogin = false;
		skips = null;
	}
	
	private boolean needSkipUserLoginCheck(HttpServletRequest r) {
		boolean result = false;
		String uri = r.getRequestURI();

		//过滤掉直接输入根路径 或者 根路径 + / 这些
        if (uri.equals(r.getContextPath()) || uri.equals(r.getContextPath()+"/")){
        	return true;
        }

		for (String s : skips ) {
			if( uri.indexOf(s) > -1 ){
				result = true;
				break;
			}
		}

		return result;
	}
}
